package net.cyue.web.easyquery.core.db.api;

import net.cyue.web.easyquery.core.db.data.PageQueryResult;
import net.cyue.web.easyquery.core.db.data.QueryPage;
import net.cyue.web.easyquery.core.db.data.QueryPageResult;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * SQL执行器接口
 */
public interface ISQLExecutor {
    /**
     * 执行查询
     * @param sql 预编译SQL
     * @param params 参数
     * @return 结果
     * @throws SQLException SQL异常
     */
    List<Map<String, Object>> query(String sql, Map<String, Object> params) throws SQLException;

    /**
     * 执行查询，返回一条数据
     * @param sql 预编译SQL
     * @param params 参数
     * @return 结果
     * @throws SQLException SQL异常
     */
    default Map<String, Object> queryOne(String sql, Map<String, Object> params)
        throws SQLException
    {
        String limitSQL = sql + " limit 1";
        List<Map<String, Object>> result = this.query(limitSQL, params);
        return result == null || result.isEmpty() ? null : result.get(0);
    }

    /**
     * 执行分页查询
     * @param sql 预编译SQL
     * @param params 参数
     * @param page 分页信息
     * @return 结果
     * @throws SQLException SQL异常
     */
    default PageQueryResult queryPage(String sql, Map<String, Object> params, QueryPage page)
        throws SQLException
    {
        String limitSQL = sql + " limit " + (page.getPageSize() * (page.getPage() - 1)) + "," + page.getPageSize();
        List<Map<String, Object>> result = this.query(limitSQL, params);
        if (page.ifDoCount()) {
            String countSql = "select count(*) as total from (" + sql + ") as t";
            List<Map<String, Object>> countResult = this.query(countSql, params);
            if (countResult == null || countResult.isEmpty()) {
                return new PageQueryResult(
                    QueryPageResult.fromPage(page, 0L),
                    result
                );
            }
            Object totalObj = countResult.get(0).get("total");
            return new PageQueryResult(
                QueryPageResult.fromPage(page, Long.parseLong(totalObj.toString())),
                result
            );
        }
        return new PageQueryResult(
            QueryPageResult.fromPage(page, null),
            result
        );
    }

    /**
     * 执行更新（insert, update, delete）
     * @param sql 预编译SQL
     * @param params 参数
     * @return 更新数量
     * @throws SQLException SQL异常
     */
    int update(String sql, Map<String, Object> params) throws SQLException;

    /**
     * 批量执行更新操作
     * @param sql 预编译SQL
     * @param paramsList 参数列表
     * @return 各条更新的影响行数
     * @throws SQLException SQL异常
     */
    default int[] batchUpdate(String sql, List<Map<String, Object>> paramsList) throws SQLException {
        Objects.requireNonNull(sql, "SQL语句不能为null");
        Objects.requireNonNull(paramsList, "参数列表不能为null");

        // 默认实现为循环单条执行，建议实现类使用JDBC的Batch操作优化性能
        int[] results = new int[paramsList.size()];
        for (int i = 0; i < paramsList.size(); i++) {
            results[i] = update(sql, paramsList.get(i));
        }
        return results;
    }
}
